home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume10 / xlisp21 / part08 < prev    next >
Encoding:
Text File  |  1990-02-26  |  57.7 KB  |  2,506 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Cognos Inc., Ottawa, Canada
  3. subject: v10i095: XLisP 2.1 sources 4b (2/2) / 5
  4. From: garym@cognos.UUCP (Gary Murphy)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 10, Issue 95
  8. Submitted-by: garym@cognos.UUCP (Gary Murphy)
  9. Archive-name: xlisp21/part08
  10.  
  11. #!/bin/sh
  12. # This is a shell archive, meaning:
  13. # 1. Remove everything above the #!/bin/sh line.
  14. # 2. Save the resulting text in a file.
  15. # 3. Execute the file with /bin/sh (not csh) to create the files:
  16. #    xlread.c
  17. #    xlstr.c
  18. #    xlstruct.c
  19. #    xlsubr.c
  20. #    xlsym.c
  21. #    xlsys.c
  22. # This archive created: Sun Feb 18 23:40:39 1990
  23. # By:    Gary Murphy ()
  24. export PATH; PATH=/bin:$PATH
  25. echo shar: extracting "'xlread.c'" '(17573 characters)'
  26. if test -f 'xlread.c'
  27. then
  28.     echo shar: over-writing existing file "'xlread.c'"
  29. fi
  30. sed 's/^X//' << \SHAR_EOF > 'xlread.c'
  31. X/* xlread - xlisp expression input routine */
  32. X/*    Copyright (c) 1985, by David Michael Betz
  33. X    All Rights Reserved
  34. X    Permission is granted for unrestricted non-commercial use    */
  35. X
  36. X#include "xlisp.h"
  37. X
  38. X/* symbol parser modes */
  39. X#define DONE    0
  40. X#define NORMAL    1
  41. X#define ESCAPE    2
  42. X
  43. X/* external variables */
  44. Xextern LVAL s_stdout,true,s_dot;
  45. Xextern LVAL s_quote,s_function,s_bquote,s_comma,s_comat;
  46. Xextern LVAL s_rtable,k_wspace,k_const,k_nmacro,k_tmacro;
  47. Xextern LVAL k_sescape,k_mescape;
  48. Xextern char buf[];
  49. X
  50. X/* external routines */
  51. Xextern FILE *osaopen();
  52. Xextern double atof();
  53. Xextern ITYPE;
  54. X
  55. X#define WSPACE "\t \f\r\n"
  56. X#define CONST1 "!$%&*+-./0123456789:<=>?@[]^_{}~"
  57. X#define CONST2 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  58. X
  59. X/* forward declarations */
  60. XFORWARD LVAL callmacro();
  61. XFORWARD LVAL psymbol(),punintern();
  62. XFORWARD LVAL pnumber(),pquote(),plist(),pvector(),pstruct();
  63. XFORWARD LVAL readlist(),tentry();
  64. X
  65. X/* xlload - load a file of xlisp expressions */
  66. Xint xlload(fname,vflag,pflag)
  67. X  char *fname; int vflag,pflag;
  68. X{
  69. X    char fullname[STRMAX+1];
  70. X    LVAL fptr,expr;
  71. X    CONTEXT cntxt;
  72. X    FILE *fp;
  73. X    int sts;
  74. X
  75. X    /* protect some pointers */
  76. X    xlstkcheck(2);
  77. X    xlsave(fptr);
  78. X    xlsave(expr);
  79. X
  80. X    /* default the extension */
  81. X    if (needsextension(fname)) {
  82. X    strcpy(fullname,fname);
  83. X    strcat(fullname,".lsp");
  84. X    fname = fullname;
  85. X    }
  86. X
  87. X    /* allocate a file node */
  88. X    fptr = cvfile(NULL);
  89. X
  90. X    /* open the file */
  91. X    if ((fp = osaopen(fname,"r")) == NULL) {
  92. X    xlpopn(2);
  93. X    return (FALSE);
  94. X    }
  95. X    setfile(fptr,fp);
  96. X
  97. X    /* print the information line */
  98. X    if (vflag)
  99. X    { sprintf(buf,"; loading \"%s\"\n",fname); stdputstr(buf); }
  100. X
  101. X    /* read, evaluate and possibly print each expression in the file */
  102. X    xlbegin(&cntxt,CF_ERROR,true);
  103. X    if (setjmp(cntxt.c_jmpbuf))
  104. X    sts = FALSE;
  105. X    else {
  106. X    while (xlread(fptr,&expr,FALSE)) {
  107. X        expr = xleval(expr);
  108. X        if (pflag)
  109. X        stdprint(expr);
  110. X    }
  111. X    sts = TRUE;
  112. X    }
  113. X    xlend(&cntxt);
  114. X
  115. X    /* close the file */
  116. X    osclose(getfile(fptr));
  117. X    setfile(fptr,NULL);
  118. X
  119. X    /* restore the stack */
  120. X    xlpopn(2);
  121. X
  122. X    /* return status */
  123. X    return (sts);
  124. X}
  125. X
  126. X/* xlread - read an xlisp expression */
  127. Xint xlread(fptr,pval,rflag)
  128. X  LVAL fptr,*pval; int rflag;
  129. X{
  130. X    int sts;
  131. X
  132. X    /* read an expression */
  133. X    while ((sts = readone(fptr,pval)) == FALSE)
  134. X    ;
  135. X
  136. X    /* return status */
  137. X    return (sts == EOF ? FALSE : TRUE);
  138. X}
  139. X
  140. X/* readone - attempt to read a single expression */
  141. Xint readone(fptr,pval)
  142. X  LVAL fptr,*pval;
  143. X{
  144. X    LVAL val,type;
  145. X    int ch;
  146. X
  147. X    /* get a character and check for EOF */
  148. X    if ((ch = xlgetc(fptr)) == EOF)
  149. X    return (EOF);
  150. X
  151. X    /* handle white space */
  152. X    if ((type = tentry(ch)) == k_wspace)
  153. X    return (FALSE);
  154. X
  155. X    /* handle symbol constituents */
  156. X    else if (type == k_const) {
  157. X    xlungetc(fptr,ch);
  158. X    *pval = psymbol(fptr);
  159. X    return (TRUE);        
  160. X    }
  161. X
  162. X    /* handle single and multiple escapes */
  163. X    else if (type == k_sescape || type == k_mescape) {
  164. X    xlungetc(fptr,ch);
  165. X    *pval = psymbol(fptr);
  166. X    return (TRUE);
  167. X    }
  168. X    
  169. X    /* handle read macros */
  170. X    else if (consp(type)) {
  171. X    if ((val = callmacro(fptr,ch)) && consp(val)) {
  172. X        *pval = car(val);
  173. X        return (TRUE);
  174. X    }
  175. X    else
  176. X        return (FALSE);
  177. X    }
  178. X
  179. X    /* handle illegal characters */
  180. X    else
  181. X    xlerror("illegal character",cvfixnum((FIXTYPE)ch));
  182. X}
  183. X
  184. X/* rmhash - read macro for '#' */
  185. XLVAL rmhash()
  186. X{
  187. X    LVAL fptr,mch,val;
  188. X    int escflag,ch;
  189. X
  190. X    /* protect some pointers */
  191. X    xlsave1(val);
  192. X
  193. X    /* get the file and macro character */
  194. X    fptr = xlgetfile();
  195. X    mch = xlgachar();
  196. X    xllastarg();
  197. X
  198. X    /* make the return value */
  199. X    val = consa(NIL);
  200. X
  201. X    /* check the next character */
  202. X    switch (ch = xlgetc(fptr)) {
  203. X    case '\'':
  204. X        rplaca(val,pquote(fptr,s_function));
  205. X        break;
  206. X    case '(':
  207. X        xlungetc(fptr,ch);
  208. X        rplaca(val,pvector(fptr));
  209. X        break;
  210. X    case 'b':
  211. X    case 'B':
  212. X        rplaca(val,pnumber(fptr,2));
  213. X        break;
  214. X    case 'o':
  215. X    case 'O':
  216. X        rplaca(val,pnumber(fptr,8));
  217. X        break;
  218. X    case 'x':
  219. X    case 'X':
  220. X            rplaca(val,pnumber(fptr,16));
  221. X        break;
  222. X    case 's':
  223. X    case 'S':
  224. X        rplaca(val,pstruct(fptr));
  225. X        break;
  226. X    case '\\':
  227. X        xlungetc(fptr,ch);
  228. X        pname(fptr,&escflag);
  229. X        ch = buf[0];
  230. X        if (strlen(buf) > 1) {
  231. X            upcase(buf);
  232. X            if (strcmp(buf,"NEWLINE") == 0)
  233. X            ch = '\n';
  234. X            else if (strcmp(buf,"SPACE") == 0)
  235. X            ch = ' ';
  236. X            else
  237. X            xlerror("unknown character name",cvstring(buf));
  238. X        }
  239. X        rplaca(val,cvchar(ch));
  240. X        break;
  241. X    case ':':
  242. X            rplaca(val,punintern(fptr));
  243. X        break;
  244. X    case '|':
  245. X            pcomment(fptr);
  246. X        val = NIL;
  247. X        break;
  248. X    default:
  249. X        xlerror("illegal character after #",cvfixnum((FIXTYPE)ch));
  250. X    }
  251. X
  252. X    /* restore the stack */
  253. X    xlpop();
  254. X
  255. X    /* return the value */
  256. X    return (val);
  257. X}
  258. X
  259. X/* rmquote - read macro for '\'' */
  260. XLVAL rmquote()
  261. X{
  262. X    LVAL fptr,mch;
  263. X
  264. X    /* get the file and macro character */
  265. X    fptr = xlgetfile();
  266. X    mch = xlgachar();
  267. X    xllastarg();
  268. X
  269. X    /* parse the quoted expression */
  270. X    return (consa(pquote(fptr,s_quote)));
  271. X}
  272. X
  273. X/* rmdquote - read macro for '"' */
  274. XLVAL rmdquote()
  275. X{
  276. X    unsigned char buf[STRMAX+1],*p,*sptr;
  277. X    LVAL fptr,str,newstr,mch;
  278. X    int len,blen,ch,d2,d3;
  279. X
  280. X    /* protect some pointers */
  281. X    xlsave1(str);
  282. X
  283. X    /* get the file and macro character */
  284. X    fptr = xlgetfile();
  285. X    mch = xlgachar();
  286. X    xllastarg();
  287. X
  288. X    /* loop looking for a closing quote */
  289. X    len = blen = 0; p = buf;
  290. X    while ((ch = checkeof(fptr)) != '"') {
  291. X
  292. X    /* handle escaped characters */
  293. X    switch (ch) {
  294. X    case '\\':
  295. X        switch (ch = checkeof(fptr)) {
  296. X        case 't':
  297. X            ch = '\011';
  298. X            break;
  299. X        case 'n':
  300. X            ch = '\012';
  301. X            break;
  302. X        case 'f':
  303. X            ch = '\014';
  304. X            break;
  305. X        case 'r':
  306. X            ch = '\015';
  307. X            break;
  308. X        default:
  309. X            if (ch >= '0' && ch <= '7') {
  310. X                d2 = checkeof(fptr);
  311. X                d3 = checkeof(fptr);
  312. X                if (d2 < '0' || d2 > '7'
  313. X                 || d3 < '0' || d3 > '7')
  314. X                xlfail("invalid octal digit");
  315. X                ch -= '0'; d2 -= '0'; d3 -= '0';
  316. X                ch = (ch << 6) | (d2 << 3) | d3;
  317. X            }
  318. X            break;
  319. X        }
  320. X    }
  321. X
  322. X    /* check for buffer overflow */
  323. X    if (blen >= STRMAX) {
  324. X         newstr = newstring(len + STRMAX + 1);
  325. X        sptr = getstring(newstr); *sptr = '\0';
  326. X        if (str) strcat(sptr,getstring(str));
  327. X        *p = '\0'; strcat(sptr,buf);
  328. X        p = buf; blen = 0;
  329. X        len += STRMAX;
  330. X        str = newstr;
  331. X    }
  332. X
  333. X    /* store the character */
  334. X    *p++ = ch; ++blen;
  335. X    }
  336. X
  337. X    /* append the last substring */
  338. X    if (str == NIL || blen) {
  339. X    newstr = newstring(len + blen + 1);
  340. X    sptr = getstring(newstr); *sptr = '\0';
  341. X    if (str) strcat(sptr,getstring(str));
  342. X    *p = '\0'; strcat(sptr,buf);
  343. X    str = newstr;
  344. X    }
  345. X
  346. X    /* restore the stack */
  347. X    xlpop();
  348. X
  349. X    /* return the new string */
  350. X    return (consa(str));
  351. X}
  352. X
  353. X/* rmbquote - read macro for '`' */
  354. XLVAL rmbquote()
  355. X{
  356. X    LVAL fptr,mch;
  357. X
  358. X    /* get the file and macro character */
  359. X    fptr = xlgetfile();
  360. X    mch = xlgachar();
  361. X    xllastarg();
  362. X
  363. X    /* parse the quoted expression */
  364. X    return (consa(pquote(fptr,s_bquote)));
  365. X}
  366. X
  367. X/* rmcomma - read macro for ',' */
  368. XLVAL rmcomma()
  369. X{
  370. X    LVAL fptr,mch,sym;
  371. X    int ch;
  372. X
  373. X    /* get the file and macro character */
  374. X    fptr = xlgetfile();
  375. X    mch = xlgachar();
  376. X    xllastarg();
  377. X
  378. X    /* check the next character */
  379. X    if ((ch = xlgetc(fptr)) == '@')
  380. X    sym = s_comat;
  381. X    else {
  382. X    xlungetc(fptr,ch);
  383. X    sym = s_comma;
  384. X    }
  385. X
  386. X    /* make the return value */
  387. X    return (consa(pquote(fptr,sym)));
  388. X}
  389. X
  390. X/* rmlpar - read macro for '(' */
  391. XLVAL rmlpar()
  392. X{
  393. X    LVAL fptr,mch;
  394. X
  395. X    /* get the file and macro character */
  396. X    fptr = xlgetfile();
  397. X    mch = xlgachar();
  398. X    xllastarg();
  399. X
  400. X    /* make the return value */
  401. X    return (consa(plist(fptr)));
  402. X}
  403. X
  404. X/* rmrpar - read macro for ')' */
  405. XLVAL rmrpar()
  406. X{
  407. X    xlfail("misplaced right paren");
  408. X}
  409. X
  410. X/* rmsemi - read macro for ';' */
  411. XLVAL rmsemi()
  412. X{
  413. X    LVAL fptr,mch;
  414. X    int ch;
  415. X
  416. X    /* get the file and macro character */
  417. X    fptr = xlgetfile();
  418. X    mch = xlgachar();
  419. X    xllastarg();
  420. X
  421. X    /* skip to end of line */
  422. X    while ((ch = xlgetc(fptr)) != EOF && ch != '\n')
  423. X    ;
  424. X
  425. X    /* return nil (nothing read) */
  426. X    return (NIL);
  427. X}
  428. X
  429. X/* pcomment - parse a comment delimited by #| and |# */
  430. XLOCAL pcomment(fptr)
  431. X  LVAL fptr;
  432. X{
  433. X    int lastch,ch,n;
  434. X
  435. X    /* look for the matching delimiter (and handle nesting) */
  436. X    for (n = 1, lastch = -1; n > 0 && (ch = xlgetc(fptr)) != EOF; ) {
  437. X    if (lastch == '|' && ch == '#')
  438. X        { --n; ch = -1; }
  439. X    else if (lastch == '#' && ch == '|')
  440. X        { ++n; ch = -1; }
  441. X    lastch = ch;
  442. X    }
  443. X}
  444. X
  445. X/* pnumber - parse a number */
  446. XLOCAL LVAL pnumber(fptr,radix)
  447. X  LVAL fptr; int radix;
  448. X{
  449. X    int digit,ch;
  450. X    long num;
  451. X    
  452. X    for (num = 0L; (ch = xlgetc(fptr)) != EOF; ) {
  453. X    if (islower(ch)) ch = toupper(ch);
  454. X    if (!('0' <= ch && ch <= '9') && !('A' <= ch && ch <= 'F'))
  455. X        break;
  456. X    if ((digit = (ch <= '9' ? ch - '0' : ch - 'A' + 10)) >= radix)
  457. X        break;
  458. X    num = num * (long)radix + (long)digit;
  459. X    }
  460. X    xlungetc(fptr,ch);
  461. X    return (cvfixnum((FIXTYPE)num));
  462. X}
  463. X
  464. X/* plist - parse a list */
  465. XLOCAL LVAL plist(fptr)
  466. X  LVAL fptr;
  467. X{
  468. X    LVAL val,expr,lastnptr,nptr;
  469. X
  470. X    /* protect some pointers */
  471. X    xlstkcheck(2);
  472. X    xlsave(val);
  473. X    xlsave(expr);
  474. X
  475. X    /* keep appending nodes until a closing paren is found */
  476. X    for (lastnptr = NIL; nextch(fptr) != ')'; )
  477. X
  478. X    /* get the next expression */
  479. X    switch (readone(fptr,&expr)) {
  480. X    case EOF:
  481. X        badeof(fptr);
  482. X    case TRUE:
  483. X
  484. X        /* check for a dotted tail */
  485. X        if (expr == s_dot) {
  486. X
  487. X        /* make sure there's a node */
  488. X        if (lastnptr == NIL)
  489. X            xlfail("invalid dotted pair");
  490. X
  491. X        /* parse the expression after the dot */
  492. X        if (!xlread(fptr,&expr,TRUE))
  493. X            badeof(fptr);
  494. X        rplacd(lastnptr,expr);
  495. X
  496. X        /* make sure its followed by a close paren */
  497. X        if (nextch(fptr) != ')')
  498. X            xlfail("invalid dotted pair");
  499. X        }
  500. X
  501. X        /* otherwise, handle a normal list element */
  502. X        else {
  503. X        nptr = consa(expr);
  504. X        if (lastnptr == NIL)
  505. X            val = nptr;
  506. X        else
  507. X            rplacd(lastnptr,nptr);
  508. X        lastnptr = nptr;
  509. X        }
  510. X        break;
  511. X    }
  512. X
  513. X    /* skip the closing paren */
  514. X    xlgetc(fptr);
  515. X
  516. X    /* restore the stack */
  517. X    xlpopn(2);
  518. X
  519. X    /* return successfully */
  520. X    return (val);
  521. X}
  522. X
  523. X/* pvector - parse a vector */
  524. XLOCAL LVAL pvector(fptr)
  525. X  LVAL fptr;
  526. X{
  527. X    LVAL list,val;
  528. X    int len,i;
  529. X
  530. X    /* protect some pointers */
  531. X    xlsave1(list);
  532. X
  533. X    /* read the list */
  534. X    list = readlist(fptr,&len);
  535. X
  536. X    /* make a vector of the appropriate length */
  537. X    val = newvector(len);
  538. X
  539. X    /* copy the list into the vector */
  540. X    for (i = 0; i < len; ++i, list = cdr(list))
  541. X    setelement(val,i,car(list));
  542. X
  543. X    /* restore the stack */
  544. X    xlpop();
  545. X
  546. X    /* return successfully */
  547. X    return (val);
  548. X}
  549. X
  550. X/* pstruct - parse a structure */
  551. XLOCAL LVAL pstruct(fptr)
  552. X  LVAL fptr;
  553. X{
  554. X    extern LVAL xlrdstruct();
  555. X    LVAL list,val;
  556. X    int len;
  557. X
  558. X    /* protect some pointers */
  559. X    xlsave1(list);
  560. X
  561. X    /* read the list */
  562. X    list = readlist(fptr,&len);
  563. X
  564. X    /* make the structure */
  565. X    val = xlrdstruct(list);
  566. X
  567. X    /* restore the stack */
  568. X    xlpop();
  569. X
  570. X    /* return successfully */
  571. X    return (val);
  572. X}
  573. X
  574. X/* pquote - parse a quoted expression */
  575. XLOCAL LVAL pquote(fptr,sym)
  576. X  LVAL fptr,sym;
  577. X{
  578. X    LVAL val,p;
  579. X
  580. X    /* protect some pointers */
  581. X    xlsave1(val);
  582. X
  583. X    /* allocate two nodes */
  584. X    val = consa(sym);
  585. X    rplacd(val,consa(NIL));
  586. X
  587. X    /* initialize the second to point to the quoted expression */
  588. X    if (!xlread(fptr,&p,TRUE))
  589. X    badeof(fptr);
  590. X    rplaca(cdr(val),p);
  591. X
  592. X    /* restore the stack */
  593. X    xlpop();
  594. X
  595. X    /* return the quoted expression */
  596. X    return (val);
  597. X}
  598. X
  599. X/* psymbol - parse a symbol name */
  600. XLOCAL LVAL psymbol(fptr)
  601. X  LVAL fptr;
  602. X{
  603. X    int escflag;
  604. X    LVAL val;
  605. X    pname(fptr,&escflag);
  606. X    return (escflag || !isnumber(buf,&val) ? xlenter(buf) : val);
  607. X}
  608. X
  609. X/* punintern - parse an uninterned symbol */
  610. XLOCAL LVAL punintern(fptr)
  611. X  LVAL fptr;
  612. X{
  613. X    int escflag;
  614. X    pname(fptr,&escflag);
  615. X    return (xlmakesym(buf));
  616. X}
  617. X
  618. X/* pname - parse a symbol/package name */
  619. XLOCAL int pname(fptr,pescflag)
  620. X  LVAL fptr; int *pescflag;
  621. X{
  622. X    int mode,ch,i;
  623. X    LVAL type;
  624. X
  625. X    /* initialize */
  626. X    *pescflag = FALSE;
  627. X    mode = NORMAL;
  628. X    i = 0;
  629. X
  630. X    /* accumulate the symbol name */
  631. X    while (mode != DONE) {
  632. X
  633. X    /* handle normal mode */
  634. X    while (mode == NORMAL)
  635. X        if ((ch = xlgetc(fptr)) == EOF)
  636. X        mode = DONE;
  637. X        else if ((type = tentry(ch)) == k_sescape) {
  638. X        i = storech(buf,i,checkeof(fptr));
  639. X        *pescflag = TRUE;
  640. X        }
  641. X        else if (type == k_mescape) {
  642. X        *pescflag = TRUE;
  643. X        mode = ESCAPE;
  644. X        }
  645. X        else if (type == k_const
  646. X         ||  (consp(type) && car(type) == k_nmacro))
  647. X        i = storech(buf,i,islower(ch) ? toupper(ch) : ch);
  648. X        else
  649. X        mode = DONE;
  650. X
  651. X    /* handle multiple escape mode */
  652. X    while (mode == ESCAPE)
  653. X        if ((ch = xlgetc(fptr)) == EOF)
  654. X        badeof(fptr);
  655. X        else if ((type = tentry(ch)) == k_sescape)
  656. X        i = storech(buf,i,checkeof(fptr));
  657. X        else if (type == k_mescape)
  658. X        mode = NORMAL;
  659. X        else
  660. X        i = storech(buf,i,ch);
  661. X    }
  662. X    buf[i] = 0;
  663. X
  664. X    /* check for a zero length name */
  665. X    if (i == 0)
  666. X    xlerror("zero length name");
  667. X
  668. X    /* unget the last character and return it */
  669. X    xlungetc(fptr,ch);
  670. X    return (ch);
  671. X}
  672. X
  673. X/* readlist - read a list terminated by a ')' */
  674. XLOCAL LVAL readlist(fptr,plen)
  675. X  LVAL fptr; int *plen;
  676. X{
  677. X    LVAL list,expr,lastnptr,nptr;
  678. X    int ch;
  679. X
  680. X    /* protect some pointers */
  681. X    xlstkcheck(2);
  682. X    xlsave(list);
  683. X    xlsave(expr);
  684. X
  685. X    /* get the open paren */
  686. X    if ((ch = nextch(fptr)) != '(')
  687. X    xlfail("expecting an open paren");
  688. X    xlgetc(fptr);
  689. X
  690. X    /* keep appending nodes until a closing paren is found */
  691. X    for (lastnptr = NIL, *plen = 0; (ch = nextch(fptr)) != ')'; ) {
  692. X
  693. X    /* check for end of file */
  694. X    if (ch == EOF)
  695. X        badeof(fptr);
  696. X
  697. X    /* get the next expression */
  698. X    switch (readone(fptr,&expr)) {
  699. X    case EOF:
  700. X        badeof(fptr);
  701. X    case TRUE:
  702. X        nptr = consa(expr);
  703. X        if (lastnptr == NIL)
  704. X        list = nptr;
  705. X        else
  706. X        rplacd(lastnptr,nptr);
  707. X        lastnptr = nptr;
  708. X        ++(*plen);
  709. X        break;
  710. X    }
  711. X    }
  712. X
  713. X    /* skip the closing paren */
  714. X    xlgetc(fptr);
  715. X
  716. X    /* restore the stack */
  717. X    xlpopn(2);
  718. X
  719. X    /* return the list */
  720. X    return (list);
  721. X}
  722. X
  723. X/* storech - store a character in the print name buffer */
  724. XLOCAL int storech(buf,i,ch)
  725. X  char *buf; int i,ch;
  726. X{
  727. X    if (i < STRMAX)
  728. X    buf[i++] = ch;
  729. X    return (i);
  730. X}
  731. X
  732. X/* tentry - get a readtable entry */
  733. XLVAL tentry(ch)
  734. X  int ch;
  735. X{
  736. X    LVAL rtable;
  737. X    rtable = getvalue(s_rtable);
  738. X    if (!vectorp(rtable) || ch < 0 || ch >= getsize(rtable))
  739. X    return (NIL);
  740. X    return (getelement(rtable,ch));
  741. X}
  742. X
  743. X/* nextch - look at the next non-blank character */
  744. XLOCAL int nextch(fptr)
  745. X  LVAL fptr;
  746. X{
  747. X    int ch;
  748. X
  749. X    /* return and save the next non-blank character */
  750. X    while ((ch = xlgetc(fptr)) != EOF && isspace(ch))
  751. X    ;
  752. X    xlungetc(fptr,ch);
  753. X    return (ch);
  754. X}
  755. X
  756. X/* checkeof - get a character and check for end of file */
  757. XLOCAL int checkeof(fptr)
  758. X  LVAL fptr;
  759. X{
  760. X    int ch;
  761. X
  762. X    if ((ch = xlgetc(fptr)) == EOF)
  763. X    badeof(fptr);
  764. X    return (ch);
  765. X}
  766. X
  767. X/* badeof - unexpected eof */
  768. XLOCAL badeof(fptr)
  769. X  LVAL fptr;
  770. X{
  771. X    xlgetc(fptr);
  772. X    xlfail("unexpected EOF");
  773. X}
  774. X
  775. X/* isnumber - check if this string is a number */
  776. Xint isnumber(str,pval)
  777. X  char *str; LVAL *pval;
  778. X{
  779. X    int dl,dr;
  780. X    char *p;
  781. X
  782. X    /* initialize */
  783. X    p = str; dl = dr = 0;
  784. X
  785. X    /* check for a sign */
  786. X    if (*p == '+' || *p == '-')
  787. X    p++;
  788. X
  789. X    /* check for a string of digits */
  790. X    while (isdigit(*p))
  791. X    p++, dl++;
  792. X
  793. X    /* check for a decimal point */
  794. X    if (*p == '.') {
  795. X    p++;
  796. X    while (isdigit(*p))
  797. X        p++, dr++;
  798. X    }
  799. X
  800. X    /* check for an exponent */
  801. X    if ((dl || dr) && *p == 'E') {
  802. X    p++;
  803. X
  804. X    /* check for a sign */
  805. X    if (*p == '+' || *p == '-')
  806. X        p++;
  807. X
  808. X    /* check for a string of digits */
  809. X    while (isdigit(*p))
  810. X        p++, dr++;
  811. X    }
  812. X
  813. X    /* make sure there was at least one digit and this is the end */
  814. X    if ((dl == 0 && dr == 0) || *p)
  815. X    return (FALSE);
  816. X
  817. X    /* convert the string to an integer and return successfully */
  818. X    if (pval) {
  819. X    if (*str == '+') ++str;
  820. X    if (str[strlen(str)-1] == '.') str[strlen(str)-1] = 0;
  821. X    *pval = (dr ? cvflonum(atof(str)) : cvfixnum(ICNV(str)));
  822. X    }
  823. X    return (TRUE);
  824. X}
  825. X
  826. X/* defmacro - define a read macro */
  827. Xdefmacro(ch,type,offset)
  828. X  int ch; LVAL type; int offset;
  829. X{
  830. X    extern FUNDEF funtab[];
  831. X    LVAL subr;
  832. X    subr = cvsubr(funtab[offset].fd_subr,funtab[offset].fd_type,offset);
  833. X    setelement(getvalue(s_rtable),ch,cons(type,subr));
  834. X}
  835. X
  836. X/* callmacro - call a read macro */
  837. XLVAL callmacro(fptr,ch)
  838. X  LVAL fptr; int ch;
  839. X{
  840. X    LVAL *newfp;
  841. X
  842. X    /* create the new call frame */
  843. X    newfp = xlsp;
  844. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  845. X    pusharg(cdr(getelement(getvalue(s_rtable),ch)));
  846. X    pusharg(cvfixnum((FIXTYPE)2));
  847. X    pusharg(fptr);
  848. X    pusharg(cvchar(ch));
  849. X    xlfp = newfp;
  850. X    return (xlapply(2));
  851. X}
  852. X
  853. X/* upcase - translate a string to upper case */
  854. XLOCAL upcase(str)
  855. X  unsigned char *str;
  856. X{
  857. X    for (; *str != '\0'; ++str)
  858. X    if (islower(*str))
  859. X        *str = toupper(*str);
  860. X}
  861. X
  862. X/* xlrinit - initialize the reader */
  863. Xxlrinit()
  864. X{
  865. X    LVAL rtable;
  866. X    char *p;
  867. X    int ch;
  868. X
  869. X    /* create the read table */
  870. X    rtable = newvector(256);
  871. X    setvalue(s_rtable,rtable);
  872. X
  873. X    /* initialize the readtable */
  874. X    for (p = WSPACE; ch = *p++; )
  875. X    setelement(rtable,ch,k_wspace);
  876. X    for (p = CONST1; ch = *p++; )
  877. X    setelement(rtable,ch,k_const);
  878. X    for (p = CONST2; ch = *p++; )
  879. X    setelement(rtable,ch,k_const);
  880. X
  881. X    /* setup the escape characters */
  882. X    setelement(rtable,'\\',k_sescape);
  883. X    setelement(rtable,'|', k_mescape);
  884. X
  885. X    /* install the read macros */
  886. X    defmacro('#', k_nmacro,FT_RMHASH);
  887. X    defmacro('\'',k_tmacro,FT_RMQUOTE);
  888. X    defmacro('"', k_tmacro,FT_RMDQUOTE);
  889. X    defmacro('`', k_tmacro,FT_RMBQUOTE);
  890. X    defmacro(',', k_tmacro,FT_RMCOMMA);
  891. X    defmacro('(', k_tmacro,FT_RMLPAR);
  892. X    defmacro(')', k_tmacro,FT_RMRPAR);
  893. X    defmacro(';', k_tmacro,FT_RMSEMI);
  894. X}
  895. X
  896. SHAR_EOF
  897. if test 17573 -ne "`wc -c 'xlread.c'`"
  898. then
  899.     echo shar: error transmitting "'xlread.c'" '(should have been 17573 characters)'
  900. fi
  901. echo shar: extracting "'xlstr.c'" '(13099 characters)'
  902. if test -f 'xlstr.c'
  903. then
  904.     echo shar: over-writing existing file "'xlstr.c'"
  905. fi
  906. sed 's/^X//' << \SHAR_EOF > 'xlstr.c'
  907. X/* xlstr - xlisp string and character built-in functions */
  908. X/*    Copyright (c) 1985, by David Michael Betz
  909. X    All Rights Reserved
  910. X    Permission is granted for unrestricted non-commercial use    */
  911. X
  912. X#include "xlisp.h"
  913. X
  914. X/* local definitions */
  915. X#define fix(n)    cvfixnum((FIXTYPE)(n))
  916. X#define TLEFT    1
  917. X#define TRIGHT    2
  918. X
  919. X/* external variables */
  920. Xextern LVAL k_start,k_end,k_1start,k_1end,k_2start,k_2end;
  921. Xextern LVAL true;
  922. Xextern char buf[];
  923. X
  924. X/* external procedures */
  925. Xextern char *strcat();
  926. X
  927. X/* forward declarations */
  928. XFORWARD LVAL strcompare();
  929. XFORWARD LVAL chrcompare();
  930. XFORWARD LVAL changecase();
  931. XFORWARD LVAL trim();
  932. X
  933. X/* string comparision functions */
  934. XLVAL xstrlss() { return (strcompare('<',FALSE)); } /* string< */
  935. XLVAL xstrleq() { return (strcompare('L',FALSE)); } /* string<= */
  936. XLVAL xstreql() { return (strcompare('=',FALSE)); } /* string= */
  937. XLVAL xstrneq() { return (strcompare('#',FALSE)); } /* string/= */
  938. XLVAL xstrgeq() { return (strcompare('G',FALSE)); } /* string>= */
  939. XLVAL xstrgtr() { return (strcompare('>',FALSE)); } /* string> */
  940. X
  941. X/* string comparison functions (not case sensitive) */
  942. XLVAL xstrilss() { return (strcompare('<',TRUE)); } /* string-lessp */
  943. XLVAL xstrileq() { return (strcompare('L',TRUE)); } /* string-not-greaterp */
  944. XLVAL xstrieql() { return (strcompare('=',TRUE)); } /* string-equal */
  945. XLVAL xstrineq() { return (strcompare('#',TRUE)); } /* string-not-equal */
  946. XLVAL xstrigeq() { return (strcompare('G',TRUE)); } /* string-not-lessp */
  947. XLVAL xstrigtr() { return (strcompare('>',TRUE)); } /* string-greaterp */
  948. X
  949. X/* strcompare - compare strings */
  950. XLOCAL LVAL strcompare(fcn,icase)
  951. X  int fcn,icase;
  952. X{
  953. X    int start1,end1,start2,end2,ch1,ch2;
  954. X    unsigned char *p1,*p2;
  955. X    LVAL str1,str2;
  956. X
  957. X    /* get the strings */
  958. X    str1 = xlgastring();
  959. X    str2 = xlgastring();
  960. X
  961. X    /* get the substring specifiers */
  962. X    getbounds(str1,k_1start,k_1end,&start1,&end1);
  963. X    getbounds(str2,k_2start,k_2end,&start2,&end2);
  964. X
  965. X    /* setup the string pointers */
  966. X    p1 = &getstring(str1)[start1];
  967. X    p2 = &getstring(str2)[start2];
  968. X
  969. X    /* compare the strings */
  970. X    for (; start1 < end1 && start2 < end2; ++start1,++start2) {
  971. X    ch1 = *p1++;
  972. X    ch2 = *p2++;
  973. X    if (icase) {
  974. X        if (isupper(ch1)) ch1 = tolower(ch1);
  975. X        if (isupper(ch2)) ch2 = tolower(ch2);
  976. X    }
  977. X    if (ch1 != ch2)
  978. X        switch (fcn) {
  979. X        case '<':    return (ch1 < ch2 ? fix(start1) : NIL);
  980. X        case 'L':    return (ch1 <= ch2 ? fix(start1) : NIL);
  981. X        case '=':    return (NIL);
  982. X        case '#':    return (fix(start1));
  983. X        case 'G':    return (ch1 >= ch2 ? fix(start1) : NIL);
  984. X        case '>':    return (ch1 > ch2 ? fix(start1) : NIL);
  985. X        }
  986. X    }
  987. X
  988. X    /* check the termination condition */
  989. X    switch (fcn) {
  990. X    case '<':    return (start1 >= end1 && start2 < end2 ? fix(start1) : NIL);
  991. X    case 'L':    return (start1 >= end1 ? fix(start1) : NIL);
  992. X    case '=':    return (start1 >= end1 && start2 >= end2 ? true : NIL);
  993. X    case '#':    return (start1 >= end1 && start2 >= end2 ? NIL : fix(start1));
  994. X    case 'G':    return (start2 >= end2 ? fix(start1) : NIL);
  995. X    case '>':    return (start2 >= end2 && start1 < end1 ? fix(start1) : NIL);
  996. X    }
  997. X}
  998. X
  999. X/* case conversion functions */
  1000. XLVAL xupcase()   { return (changecase('U',FALSE)); }
  1001. XLVAL xdowncase() { return (changecase('D',FALSE)); }
  1002. X
  1003. X/* destructive case conversion functions */
  1004. XLVAL xnupcase()   { return (changecase('U',TRUE)); }
  1005. XLVAL xndowncase() { return (changecase('D',TRUE)); }
  1006. X
  1007. X/* changecase - change case */
  1008. XLOCAL LVAL changecase(fcn,destructive)
  1009. X  int fcn,destructive;
  1010. X{
  1011. X    unsigned char *srcp,*dstp;
  1012. X    int start,end,len,ch,i;
  1013. X    LVAL src,dst;
  1014. X
  1015. X    /* get the string */
  1016. X    src = xlgastring();
  1017. X
  1018. X    /* get the substring specifiers */
  1019. X    getbounds(src,k_start,k_end,&start,&end);
  1020. X    len = getslength(src) - 1;
  1021. X
  1022. X    /* make a destination string */
  1023. X    dst = (destructive ? src : newstring(len+1));
  1024. X
  1025. X    /* setup the string pointers */
  1026. X    srcp = getstring(src);
  1027. X    dstp = getstring(dst);
  1028. X
  1029. X    /* copy the source to the destination */
  1030. X    for (i = 0; i < len; ++i) {
  1031. X    ch = *srcp++;
  1032. X    if (i >= start && i < end)
  1033. X        switch (fcn) {
  1034. X        case 'U':    if (islower(ch)) ch = toupper(ch); break;
  1035. X        case 'D':    if (isupper(ch)) ch = tolower(ch); break;
  1036. X        }
  1037. X    *dstp++ = ch;
  1038. X    }
  1039. X    *dstp = '\0';
  1040. X
  1041. X    /* return the new string */
  1042. X    return (dst);
  1043. X}
  1044. X
  1045. X/* trim functions */
  1046. XLVAL xtrim()      { return (trim(TLEFT|TRIGHT)); }
  1047. XLVAL xlefttrim()  { return (trim(TLEFT)); }
  1048. XLVAL xrighttrim() { return (trim(TRIGHT)); }
  1049. X
  1050. X/* trim - trim character from a string */
  1051. XLOCAL LVAL trim(fcn)
  1052. X  int fcn;
  1053. X{
  1054. X    unsigned char *leftp,*rightp,*dstp;
  1055. X    LVAL bag,src,dst;
  1056. X
  1057. X    /* get the bag and the string */
  1058. X    bag = xlgastring();
  1059. X    src = xlgastring();
  1060. X    xllastarg();
  1061. X
  1062. X    /* setup the string pointers */
  1063. X    leftp = getstring(src);
  1064. X    rightp = leftp + getslength(src) - 2;
  1065. X
  1066. X    /* trim leading characters */
  1067. X    if (fcn & TLEFT)
  1068. X    while (leftp <= rightp && inbag(*leftp,bag))
  1069. X        ++leftp;
  1070. X
  1071. X    /* trim character from the right */
  1072. X    if (fcn & TRIGHT)
  1073. X    while (rightp >= leftp && inbag(*rightp,bag))
  1074. X        --rightp;
  1075. X
  1076. X    /* make a destination string and setup the pointer */
  1077. X    dst = newstring((int)(rightp-leftp+2));
  1078. X    dstp = getstring(dst);
  1079. X
  1080. X    /* copy the source to the destination */
  1081. X    while (leftp <= rightp)
  1082. X    *dstp++ = *leftp++;
  1083. X    *dstp = '\0';
  1084. X
  1085. X    /* return the new string */
  1086. X    return (dst);
  1087. X}
  1088. X
  1089. X/* getbounds - get the start and end bounds of a string */
  1090. XLOCAL getbounds(str,skey,ekey,pstart,pend)
  1091. X  LVAL str,skey,ekey; int *pstart,*pend;
  1092. X{
  1093. X    LVAL arg;
  1094. X    int len;
  1095. X
  1096. X    /* get the length of the string */
  1097. X    len = getslength(str) - 1;
  1098. X
  1099. X    /* get the starting index */
  1100. X    if (xlgkfixnum(skey,&arg)) {
  1101. X    *pstart = (int)getfixnum(arg);
  1102. X    if (*pstart < 0 || *pstart > len)
  1103. X        xlerror("string index out of bounds",arg);
  1104. X    }
  1105. X    else
  1106. X    *pstart = 0;
  1107. X
  1108. X    /* get the ending index */
  1109. X    if (xlgkfixnum(ekey,&arg)) {
  1110. X    *pend = (int)getfixnum(arg);
  1111. X    if (*pend < 0 || *pend > len)
  1112. X        xlerror("string index out of bounds",arg);
  1113. X    }
  1114. X    else
  1115. X    *pend = len;
  1116. X
  1117. X    /* make sure the start is less than or equal to the end */
  1118. X    if (*pstart > *pend)
  1119. X    xlerror("starting index error",cvfixnum((FIXTYPE)*pstart));
  1120. X}
  1121. X
  1122. X/* inbag - test if a character is in a bag */
  1123. XLOCAL int inbag(ch,bag)
  1124. X  int ch; LVAL bag;
  1125. X{
  1126. X    unsigned char *p;
  1127. X    for (p = getstring(bag); *p != '\0'; ++p)
  1128. X    if (*p == ch)
  1129. X        return (TRUE);
  1130. X    return (FALSE);
  1131. X}
  1132. X
  1133. X/* xstrcat - concatenate a bunch of strings */
  1134. XLVAL xstrcat()
  1135. X{
  1136. X    LVAL *saveargv,tmp,val;
  1137. X    unsigned char *str;
  1138. X    int saveargc,len;
  1139. X
  1140. X    /* save the argument list */
  1141. X    saveargv = xlargv;
  1142. X    saveargc = xlargc;
  1143. X
  1144. X    /* find the length of the new string */
  1145. X    for (len = 0; moreargs(); ) {
  1146. X    tmp = xlgastring();
  1147. X    len += (int)getslength(tmp) - 1;
  1148. X    }
  1149. X
  1150. X    /* create the result string */
  1151. X    val = newstring(len+1);
  1152. X    str = getstring(val);
  1153. X
  1154. X    /* restore the argument list */
  1155. X    xlargv = saveargv;
  1156. X    xlargc = saveargc;
  1157. X    
  1158. X    /* combine the strings */
  1159. X    for (*str = '\0'; moreargs(); ) {
  1160. X    tmp = nextarg();
  1161. X    strcat(str,getstring(tmp));
  1162. X    }
  1163. X
  1164. X    /* return the new string */
  1165. X    return (val);
  1166. X}
  1167. X
  1168. X/* xsubseq - return a subsequence */
  1169. XLVAL xsubseq()
  1170. X{
  1171. X    unsigned char *srcp,*dstp;
  1172. X    int start,end,len;
  1173. X    LVAL src,dst;
  1174. X
  1175. X    /* get string and starting and ending positions */
  1176. X    src = xlgastring();
  1177. X
  1178. X    /* get the starting position */
  1179. X    dst = xlgafixnum(); start = (int)getfixnum(dst);
  1180. X    if (start < 0 || start > getslength(src) - 1)
  1181. X    xlerror("string index out of bounds",dst);
  1182. X
  1183. X    /* get the ending position */
  1184. X    if (moreargs()) {
  1185. X    dst = xlgafixnum(); end = (int)getfixnum(dst);
  1186. X    if (end < 0 || end > getslength(src) - 1)
  1187. X        xlerror("string index out of bounds",dst);
  1188. X    }
  1189. X    else
  1190. X    end = getslength(src) - 1;
  1191. X    xllastarg();
  1192. X
  1193. X    /* setup the source pointer */
  1194. X    srcp = getstring(src) + start;
  1195. X    len = end - start;
  1196. X
  1197. X    /* make a destination string and setup the pointer */
  1198. X    dst = newstring(len+1);
  1199. X    dstp = getstring(dst);
  1200. X
  1201. X    /* copy the source to the destination */
  1202. X    while (--len >= 0)
  1203. X    *dstp++ = *srcp++;
  1204. X    *dstp = '\0';
  1205. X
  1206. X    /* return the substring */
  1207. X    return (dst);
  1208. X}
  1209. X
  1210. X/* xstring - return a string consisting of a single character */
  1211. XLVAL xstring()
  1212. X{
  1213. X    LVAL arg;
  1214. X
  1215. X    /* get the argument */
  1216. X    arg = xlgetarg();
  1217. X    xllastarg();
  1218. X
  1219. X    /* make sure its not NIL */
  1220. X    if (null(arg))
  1221. X    xlbadtype(arg);
  1222. X
  1223. X    /* check the argument type */
  1224. X    switch (ntype(arg)) {
  1225. X    case STRING:
  1226. X    return (arg);
  1227. X    case SYMBOL:
  1228. X    return (getpname(arg));
  1229. X    case CHAR:
  1230. X    buf[0] = (int)getchcode(arg);
  1231. X    buf[1] = '\0';
  1232. X    return (cvstring(buf));
  1233. X    default:
  1234. X    xlbadtype(arg);
  1235. X    }
  1236. X}
  1237. X
  1238. X/* xchar - extract a character from a string */
  1239. XLVAL xchar()
  1240. X{
  1241. X    LVAL str,num;
  1242. X    int n;
  1243. X
  1244. X    /* get the string and the index */
  1245. X    str = xlgastring();
  1246. X    num = xlgafixnum();
  1247. X    xllastarg();
  1248. X
  1249. X    /* range check the index */
  1250. X    if ((n = (int)getfixnum(num)) < 0 || n >= getslength(str) - 1)
  1251. X    xlerror("index out of range",num);
  1252. X
  1253. X    /* return the character */
  1254. X    return (cvchar(getstring(str)[n]));
  1255. X}
  1256. X
  1257. X/* xcharint - convert an integer to a character */
  1258. XLVAL xcharint()
  1259. X{
  1260. X    LVAL arg;
  1261. X    arg = xlgachar();
  1262. X    xllastarg();
  1263. X    return (cvfixnum((FIXTYPE)getchcode(arg)));
  1264. X}
  1265. X
  1266. X/* xintchar - convert a character to an integer */
  1267. XLVAL xintchar()
  1268. X{
  1269. X    LVAL arg;
  1270. X    arg = xlgafixnum();
  1271. X    xllastarg();
  1272. X    return (cvchar((int)getfixnum(arg)));
  1273. X}
  1274. X
  1275. X/* xuppercasep - built-in function 'upper-case-p' */
  1276. XLVAL xuppercasep()
  1277. X{
  1278. X    int ch;
  1279. X    ch = getchcode(xlgachar());
  1280. X    xllastarg();
  1281. X    return (isupper(ch) ? true : NIL);
  1282. X}
  1283. X
  1284. X/* xlowercasep - built-in function 'lower-case-p' */
  1285. XLVAL xlowercasep()
  1286. X{
  1287. X    int ch;
  1288. X    ch = getchcode(xlgachar());
  1289. X    xllastarg();
  1290. X    return (islower(ch) ? true : NIL);
  1291. X}
  1292. X
  1293. X/* xbothcasep - built-in function 'both-case-p' */
  1294. XLVAL xbothcasep()
  1295. X{
  1296. X    int ch;
  1297. X    ch = getchcode(xlgachar());
  1298. X    xllastarg();
  1299. X    return (isupper(ch) || islower(ch) ? true : NIL);
  1300. X}
  1301. X
  1302. X/* xdigitp - built-in function 'digit-char-p' */
  1303. XLVAL xdigitp()
  1304. X{
  1305. X    int ch;
  1306. X    ch = getchcode(xlgachar());
  1307. X    xllastarg();
  1308. X    return (isdigit(ch) ? cvfixnum((FIXTYPE)(ch - '0')) : NIL);
  1309. X}
  1310. X
  1311. X/* xcharcode - built-in function 'char-code' */
  1312. XLVAL xcharcode()
  1313. X{
  1314. X    int ch;
  1315. X    ch = getchcode(xlgachar());
  1316. X    xllastarg();
  1317. X    return (cvfixnum((FIXTYPE)ch));
  1318. X}
  1319. X
  1320. X/* xcodechar - built-in function 'code-char' */
  1321. XLVAL xcodechar()
  1322. X{
  1323. X    LVAL arg;
  1324. X    int ch;
  1325. X    arg = xlgafixnum(); ch = getfixnum(arg);
  1326. X    xllastarg();
  1327. X    return (ch >= 0 && ch <= 127 ? cvchar(ch) : NIL);
  1328. X}
  1329. X
  1330. X/* xchupcase - built-in function 'char-upcase' */
  1331. XLVAL xchupcase()
  1332. X{
  1333. X    LVAL arg;
  1334. X    int ch;
  1335. X    arg = xlgachar(); ch = getchcode(arg);
  1336. X    xllastarg();
  1337. X    return (islower(ch) ? cvchar(toupper(ch)) : arg);
  1338. X}
  1339. X
  1340. X/* xchdowncase - built-in function 'char-downcase' */
  1341. XLVAL xchdowncase()
  1342. X{
  1343. X    LVAL arg;
  1344. X    int ch;
  1345. X    arg = xlgachar(); ch = getchcode(arg);
  1346. X    xllastarg();
  1347. X    return (isupper(ch) ? cvchar(tolower(ch)) : arg);
  1348. X}
  1349. X
  1350. X/* xdigitchar - built-in function 'digit-char' */
  1351. XLVAL xdigitchar()
  1352. X{
  1353. X    LVAL arg;
  1354. X    int n;
  1355. X    arg = xlgafixnum(); n = getfixnum(arg);
  1356. X    xllastarg();
  1357. X    return (n >= 0 && n <= 9 ? cvchar(n + '0') : NIL);
  1358. X}
  1359. X
  1360. X/* xalphanumericp - built-in function 'alphanumericp' */
  1361. XLVAL xalphanumericp()
  1362. X{
  1363. X    int ch;
  1364. X    ch = getchcode(xlgachar());
  1365. X    xllastarg();
  1366. X    return (isupper(ch) || islower(ch) || isdigit(ch) ? true : NIL);
  1367. X}
  1368. X
  1369. X/* character comparision functions */
  1370. XLVAL xchrlss() { return (chrcompare('<',FALSE)); } /* char< */
  1371. XLVAL xchrleq() { return (chrcompare('L',FALSE)); } /* char<= */
  1372. XLVAL xchreql() { return (chrcompare('=',FALSE)); } /* char= */
  1373. XLVAL xchrneq() { return (chrcompare('#',FALSE)); } /* char/= */
  1374. XLVAL xchrgeq() { return (chrcompare('G',FALSE)); } /* char>= */
  1375. XLVAL xchrgtr() { return (chrcompare('>',FALSE)); } /* char> */
  1376. X
  1377. X/* character comparision functions (case insensitive) */
  1378. XLVAL xchrilss() { return (chrcompare('<',TRUE)); } /* char-lessp */
  1379. XLVAL xchrileq() { return (chrcompare('L',TRUE)); } /* char-not-greaterp */
  1380. XLVAL xchrieql() { return (chrcompare('=',TRUE)); } /* char-equalp */
  1381. XLVAL xchrineq() { return (chrcompare('#',TRUE)); } /* char-not-equalp */
  1382. XLVAL xchrigeq() { return (chrcompare('G',TRUE)); } /* char-not-lessp */
  1383. XLVAL xchrigtr() { return (chrcompare('>',TRUE)); } /* char-greaterp */
  1384. X
  1385. X/* chrcompare - compare characters */
  1386. XLOCAL LVAL chrcompare(fcn,icase)
  1387. X  int fcn,icase;
  1388. X{
  1389. X    int ch1,ch2,icmp;
  1390. X    LVAL arg;
  1391. X    
  1392. X    /* get the characters */
  1393. X    arg = xlgachar(); ch1 = getchcode(arg);
  1394. X
  1395. X    /* convert to lowercase if case insensitive */
  1396. X    if (icase && isupper(ch1))
  1397. X    ch1 = tolower(ch1);
  1398. X
  1399. X    /* handle each remaining argument */
  1400. X    for (icmp = TRUE; icmp && moreargs(); ch1 = ch2) {
  1401. X
  1402. X    /* get the next argument */
  1403. X    arg = xlgachar(); ch2 = getchcode(arg);
  1404. X
  1405. X    /* convert to lowercase if case insensitive */
  1406. X    if (icase && isupper(ch2))
  1407. X        ch2 = tolower(ch2);
  1408. X
  1409. X    /* compare the characters */
  1410. X    switch (fcn) {
  1411. X    case '<':    icmp = (ch1 < ch2); break;
  1412. X    case 'L':    icmp = (ch1 <= ch2); break;
  1413. X    case '=':    icmp = (ch1 == ch2); break;
  1414. X    case '#':    icmp = (ch1 != ch2); break;
  1415. X    case 'G':    icmp = (ch1 >= ch2); break;
  1416. X    case '>':    icmp = (ch1 > ch2); break;
  1417. X    }
  1418. X    }
  1419. X
  1420. X    /* return the result */
  1421. X    return (icmp ? true : NIL);
  1422. X}
  1423. X
  1424. SHAR_EOF
  1425. if test 13099 -ne "`wc -c 'xlstr.c'`"
  1426. then
  1427.     echo shar: error transmitting "'xlstr.c'" '(should have been 13099 characters)'
  1428. fi
  1429. echo shar: extracting "'xlstruct.c'" '(10906 characters)'
  1430. if test -f 'xlstruct.c'
  1431. then
  1432.     echo shar: over-writing existing file "'xlstruct.c'"
  1433. fi
  1434. sed 's/^X//' << \SHAR_EOF > 'xlstruct.c'
  1435. X/* xlstruct.c - the defstruct facility */
  1436. X/*    Copyright (c) 1988, by David Michael Betz
  1437. X    All Rights Reserved
  1438. X    Permission is granted for unrestricted non-commercial use    */
  1439. X
  1440. X#include "xlisp.h"
  1441. X
  1442. X/* external variables */
  1443. Xextern LVAL xlenv,xlfenv;
  1444. Xextern LVAL s_lambda,s_quote,lk_key,true;
  1445. Xextern char buf[];
  1446. X
  1447. X/* local variables */
  1448. Xstatic prefix[STRMAX+1];
  1449. X
  1450. X/* xmkstruct - the '%make-struct' function */
  1451. XLVAL xmkstruct()
  1452. X{
  1453. X    LVAL type,val;
  1454. X    int i;
  1455. X
  1456. X    /* get the structure type */
  1457. X    type = xlgasymbol();
  1458. X
  1459. X    /* make the structure */
  1460. X    val = newstruct(type,xlargc);
  1461. X
  1462. X    /* store each argument */
  1463. X    for (i = 1; moreargs(); ++i)
  1464. X    setelement(val,i,nextarg());
  1465. X    xllastarg();
  1466. X
  1467. X    /* return the structure */
  1468. X    return (val);
  1469. X}
  1470. X
  1471. X/* xcpystruct - the '%copy-struct' function */
  1472. XLVAL xcpystruct()
  1473. X{
  1474. X    LVAL str,val;
  1475. X    int size,i;
  1476. X    str = xlgastruct();
  1477. X    xllastarg();
  1478. X    size = getsize(str);
  1479. X    val = newstruct(getelement(str,0),size-1);
  1480. X    for (i = 1; i < size; ++i)
  1481. X    setelement(val,i,getelement(str,i));
  1482. X    return (val);
  1483. X}
  1484. X
  1485. X/* xstrref - the '%struct-ref' function */
  1486. XLVAL xstrref()
  1487. X{
  1488. X    LVAL str,val;
  1489. X    int i;
  1490. X    str = xlgastruct();
  1491. X    val = xlgafixnum(); i = (int)getfixnum(val);
  1492. X    xllastarg();
  1493. X    return (getelement(str,i));
  1494. X}
  1495. X
  1496. X/* xstrset - the '%struct-set' function */
  1497. XLVAL xstrset()
  1498. X{
  1499. X    LVAL str,val;
  1500. X    int i;
  1501. X    str = xlgastruct();
  1502. X    val = xlgafixnum(); i = (int)getfixnum(val);
  1503. X    val = xlgetarg();
  1504. X    xllastarg();
  1505. X    setelement(str,i,val);
  1506. X    return (val);
  1507. X}
  1508. X
  1509. X/* xstrtypep - the '%struct-type-p' function */
  1510. XLVAL xstrtypep()
  1511. X{
  1512. X    LVAL type,val;
  1513. X    type = xlgasymbol();
  1514. X    val = xlgetarg();
  1515. X    xllastarg();
  1516. X    return (structp(val) && getelement(val,0) == type ? true : NIL);
  1517. X}
  1518. X
  1519. X/* xdefstruct - the 'defstruct' special form */
  1520. XLVAL xdefstruct()
  1521. X{
  1522. X    LVAL structname,slotname,defexpr,sym,tmp,args,body;
  1523. X    LVAL options,oargs,slots;
  1524. X    char *pname;
  1525. X    int slotn;
  1526. X    
  1527. X    /* protect some pointers */
  1528. X    xlstkcheck(6);
  1529. X    xlsave(structname);
  1530. X    xlsave(slotname);
  1531. X    xlsave(defexpr);
  1532. X    xlsave(args);
  1533. X    xlsave(body);
  1534. X    xlsave(tmp);
  1535. X    
  1536. X    /* initialize */
  1537. X    args = body = NIL;
  1538. X    slotn = 0;
  1539. X
  1540. X    /* get the structure name */
  1541. X    tmp = xlgetarg();
  1542. X    if (symbolp(tmp)) {
  1543. X    structname = tmp;
  1544. X    strcpy(prefix,getstring(getpname(structname)));
  1545. X    strcat(prefix,"-");
  1546. X    }
  1547. X
  1548. X    /* get the structure name and options */
  1549. X    else if (consp(tmp) && symbolp(car(tmp))) {
  1550. X    structname = car(tmp);
  1551. X    strcpy(prefix,getstring(getpname(structname)));
  1552. X    strcat(prefix,"-");
  1553. X
  1554. X    /* handle the list of options */
  1555. X    for (options = cdr(tmp); consp(options); options = cdr(options)) {
  1556. X
  1557. X        /* get the next argument */
  1558. X        tmp = car(options);
  1559. X        
  1560. X        /* handle options that don't take arguments */
  1561. X        if (symbolp(tmp)) {
  1562. X        pname = getstring(getpname(tmp));
  1563. X        xlerror("unknown option",tmp);
  1564. X        }
  1565. X
  1566. X        /* handle options that take arguments */
  1567. X        else if (consp(tmp) && symbolp(car(tmp))) {
  1568. X        pname = getstring(getpname(car(tmp)));
  1569. X        oargs = cdr(tmp);
  1570. X
  1571. X        /* check for the :CONC-NAME keyword */
  1572. X        if (strcmp(pname,":CONC-NAME") == 0) {
  1573. X
  1574. X            /* get the name of the structure to include */
  1575. X            if (!consp(oargs) || !symbolp(car(oargs)))
  1576. X            xlerror("expecting a symbol",oargs);
  1577. X
  1578. X            /* save the prefix */
  1579. X            strcpy(prefix,getstring(getpname(car(oargs))));
  1580. X        }
  1581. X
  1582. X        /* check for the :INCLUDE keyword */
  1583. X        else if (strcmp(pname,":INCLUDE") == 0) {
  1584. X
  1585. X            /* get the name of the structure to include */
  1586. X            if (!consp(oargs) || !symbolp(car(oargs)))
  1587. X            xlerror("expecting a structure name",oargs);
  1588. X            tmp = car(oargs);
  1589. X            oargs = cdr(oargs);
  1590. X
  1591. X            /* add each slot from the included structure */
  1592. X            slots = xlgetprop(tmp,xlenter("*STRUCT-SLOTS*"));
  1593. X            for (; consp(slots); slots = cdr(slots)) {
  1594. X            if (consp(car(slots)) && consp(cdr(car(slots)))) {
  1595. X
  1596. X                /* get the next slot description */
  1597. X                tmp = car(slots);
  1598. X
  1599. X                /* create the slot access functions */
  1600. X                addslot(car(tmp),car(cdr(tmp)),++slotn,&args,&body);
  1601. X            }
  1602. X            }
  1603. X
  1604. X            /* handle slot initialization overrides */
  1605. X            for (; consp(oargs); oargs = cdr(oargs)) {
  1606. X            tmp = car(oargs);
  1607. X            if (symbolp(tmp)) {
  1608. X                slotname = tmp;
  1609. X                defexpr = NIL;
  1610. X            }
  1611. X            else if (consp(tmp) && symbolp(car(tmp))) {
  1612. X                slotname = car(tmp);
  1613. X                defexpr = (consp(cdr(tmp)) ? car(cdr(tmp)) : NIL);
  1614. X            }
  1615. X            else
  1616. X                xlerror("bad slot description",tmp);
  1617. X            updateslot(args,slotname,defexpr);
  1618. X            }
  1619. X        }
  1620. X        else
  1621. X            xlerror("unknown option",tmp);
  1622. X        }
  1623. X        else
  1624. X        xlerror("bad option syntax",tmp);
  1625. X    }
  1626. X    }
  1627. X
  1628. X    /* get each of the structure members */
  1629. X    while (moreargs()) {
  1630. X    
  1631. X    /* get the slot name and default value expression */
  1632. X    tmp = xlgetarg();
  1633. X    if (symbolp(tmp)) {
  1634. X        slotname = tmp;
  1635. X        defexpr = NIL;
  1636. X    }
  1637. X    else if (consp(tmp) && symbolp(car(tmp))) {
  1638. X        slotname = car(tmp);
  1639. X        defexpr = (consp(cdr(tmp)) ? car(cdr(tmp)) : NIL);
  1640. X    }
  1641. X    else
  1642. X        xlerror("bad slot description",tmp);
  1643. X    
  1644. X    /* create a closure for non-trival default expressions */
  1645. X    if (defexpr != NIL) {
  1646. X        tmp = newclosure(NIL,s_lambda,xlenv,xlfenv);
  1647. X        setbody(tmp,cons(defexpr,NIL));
  1648. X        tmp = cons(tmp,NIL);
  1649. X        defexpr = tmp;
  1650. X    }
  1651. X
  1652. X    /* create the slot access functions */
  1653. X    addslot(slotname,defexpr,++slotn,&args,&body);
  1654. X    }
  1655. X    
  1656. X    /* store the slotnames and default expressions */
  1657. X    xlputprop(structname,args,xlenter("*STRUCT-SLOTS*"));
  1658. X
  1659. X    /* enter the MAKE-xxx symbol */
  1660. X    sprintf(buf,"MAKE-%s",getstring(getpname(structname)));
  1661. X    sym = xlenter(buf);
  1662. X
  1663. X    /* make the MAKE-xxx function */
  1664. X    args = cons(lk_key,args);
  1665. X    tmp = cons(structname,NIL);
  1666. X    tmp = cons(s_quote,tmp);
  1667. X    body = cons(tmp,body);
  1668. X    body = cons(xlenter("%MAKE-STRUCT"),body);
  1669. X    body = cons(body,NIL);
  1670. X    setfunction(sym,
  1671. X        xlclose(sym,s_lambda,args,body,xlenv,xlfenv));
  1672. X
  1673. X    /* enter the xxx-P symbol */
  1674. X    sprintf(buf,"%s-P",getstring(getpname(structname)));
  1675. X    sym = xlenter(buf);
  1676. X
  1677. X    /* make the xxx-P function */
  1678. X    args = cons(xlenter("X"),NIL);
  1679. X    body = cons(xlenter("X"),NIL);
  1680. X    tmp = cons(structname,NIL);
  1681. X    tmp = cons(s_quote,tmp);
  1682. X    body = cons(tmp,body);
  1683. X    body = cons(xlenter("%STRUCT-TYPE-P"),body);
  1684. X    body = cons(body,NIL);
  1685. X    setfunction(sym,
  1686. X        xlclose(sym,s_lambda,args,body,NIL,NIL));
  1687. X
  1688. X    /* enter the COPY-xxx symbol */
  1689. X    sprintf(buf,"COPY-%s",getstring(getpname(structname)));
  1690. X    sym = xlenter(buf);
  1691. X
  1692. X    /* make the COPY-xxx function */
  1693. X    args = cons(xlenter("X"),NIL);
  1694. X    body = cons(xlenter("X"),NIL);
  1695. X    body = cons(xlenter("%COPY-STRUCT"),body);
  1696. X    body = cons(body,NIL);
  1697. X    setfunction(sym,
  1698. X        xlclose(sym,s_lambda,args,body,NIL,NIL));
  1699. X
  1700. X    /* restore the stack */
  1701. X    xlpopn(6);
  1702. X
  1703. X    /* return the structure name */
  1704. X    return (structname);
  1705. X}
  1706. X
  1707. X/* xlrdstruct - convert a list to a structure (used by the reader) */
  1708. XLVAL xlrdstruct(list)
  1709. X  LVAL list;
  1710. X{
  1711. X    LVAL structname,sym,slotname,expr,last,val;
  1712. X
  1713. X    /* protect the new structure */
  1714. X    xlsave1(expr);
  1715. X
  1716. X    /* get the structure name */
  1717. X    if (!consp(list) || !symbolp(car(list)))
  1718. X    xlerror("bad structure initialization list",list);
  1719. X    structname = car(list);
  1720. X    list = cdr(list);
  1721. X
  1722. X    /* enter the MAKE-xxx symbol */
  1723. X    sprintf(buf,"MAKE-%s",getstring(getpname(structname)));
  1724. X
  1725. X    /* initialize the MAKE-xxx function call expression */
  1726. X    expr = cons(xlenter(buf),NIL);
  1727. X    last = expr;
  1728. X
  1729. X    /* turn the rest of the initialization list into keyword arguments */
  1730. X    while (consp(list) && consp(cdr(list))) {
  1731. X
  1732. X    /* get the slot keyword name */
  1733. X    slotname = car(list);
  1734. X    if (!symbolp(slotname))
  1735. X        xlerror("expecting a slot name",slotname);
  1736. X    sprintf(buf,":%s",getstring(getpname(slotname)));
  1737. X
  1738. X    /* add the slot keyword */
  1739. X    rplacd(last,cons(xlenter(buf),NIL));
  1740. X    last = cdr(last);
  1741. X    list = cdr(list);
  1742. X
  1743. X    /* add the value expression */
  1744. X    rplacd(last,cons(car(list),NIL));
  1745. X    last = cdr(last);
  1746. X    list = cdr(list);
  1747. X    }
  1748. X
  1749. X    /* make sure all of the initializers were used */
  1750. X    if (consp(list))
  1751. X    xlerror("bad structure initialization list",list);
  1752. X
  1753. X    /* invoke the creation function */
  1754. X    val = xleval(expr);
  1755. X
  1756. X    /* restore the stack */
  1757. X    xlpop();
  1758. X
  1759. X    /* return the new structure */
  1760. X    return (val);
  1761. X}
  1762. X
  1763. X/* xlprstruct - print a structure (used by printer) */
  1764. Xxlprstruct(fptr,vptr,flag)
  1765. X  LVAL fptr,vptr; int flag;
  1766. X{
  1767. X    LVAL next;
  1768. X    int i,n;
  1769. X    xlputc(fptr,'#'); xlputc(fptr,'S'); xlputc(fptr,'(');
  1770. X    xlprint(fptr,getelement(vptr,0),flag);
  1771. X    next = xlgetprop(getelement(vptr,0),xlenter("*STRUCT-SLOTS*"));
  1772. X    for (i = 1, n = getsize(vptr) - 1; i <= n && consp(next); ++i) {
  1773. X    if (consp(car(next))) { /* should always succeed */
  1774. X        xlputc(fptr,' ');
  1775. X        xlprint(fptr,car(car(next)),flag);
  1776. X        xlputc(fptr,' ');
  1777. X        xlprint(fptr,getelement(vptr,i),flag);
  1778. X    }
  1779. X    next = cdr(next);
  1780. X    }
  1781. X    xlputc(fptr,')');
  1782. X}
  1783. X
  1784. X/* addslot - make the slot access functions */
  1785. XLOCAL addslot(slotname,defexpr,slotn,pargs,pbody)
  1786. X  LVAL slotname,defexpr; int slotn; LVAL *pargs,*pbody;
  1787. X{
  1788. X    LVAL sym,args,body,tmp;
  1789. X    
  1790. X    /* protect some pointers */
  1791. X    xlstkcheck(4);
  1792. X    xlsave(sym);
  1793. X    xlsave(args);
  1794. X    xlsave(body);
  1795. X    xlsave(tmp);
  1796. X    
  1797. X    /* construct the update function name */
  1798. X    sprintf(buf,"%s%s",prefix,getstring(getpname(slotname)));
  1799. X    sym = xlenter(buf);
  1800. X    
  1801. X    /* make the access function */
  1802. X    args = cons(xlenter("S"),NIL);
  1803. X    body = cons(cvfixnum((FIXTYPE)slotn),NIL);
  1804. X    body = cons(xlenter("S"),body);
  1805. X    body = cons(xlenter("%STRUCT-REF"),body);
  1806. X    body = cons(body,NIL);
  1807. X    setfunction(sym,
  1808. X        xlclose(sym,s_lambda,args,body,NIL,NIL));
  1809. X
  1810. X    /* make the update function */
  1811. X    args = cons(xlenter("V"),NIL);
  1812. X    args = cons(xlenter("S"),args);
  1813. X    body = cons(xlenter("V"),NIL);
  1814. X    body = cons(cvfixnum((FIXTYPE)slotn),body);
  1815. X    body = cons(xlenter("S"),body);
  1816. X    body = cons(xlenter("%STRUCT-SET"),body);
  1817. X    body = cons(body,NIL);
  1818. X    xlputprop(sym,
  1819. X          xlclose(NIL,s_lambda,args,body,NIL,NIL),
  1820. X          xlenter("*SETF*"));
  1821. X
  1822. X    /* add the slotname to the make-xxx keyword list */
  1823. X    tmp = cons(defexpr,NIL);
  1824. X    tmp = cons(slotname,tmp);
  1825. X    tmp = cons(tmp,NIL);
  1826. X    if ((args = *pargs) == NIL)
  1827. X    *pargs = tmp;
  1828. X    else {
  1829. X    while (cdr(args) != NIL)
  1830. X        args = cdr(args);
  1831. X    rplacd(args,tmp);
  1832. X    }
  1833. X    
  1834. X    /* add the slotname to the %make-xxx argument list */
  1835. X    tmp = cons(slotname,NIL);
  1836. X    if ((body = *pbody) == NIL)
  1837. X    *pbody = tmp;
  1838. X    else {
  1839. X    while (cdr(body) != NIL)
  1840. X        body = cdr(body);
  1841. X    rplacd(body,tmp);
  1842. X    }
  1843. X
  1844. X    /* restore the stack */
  1845. X    xlpopn(4);
  1846. X}
  1847. X
  1848. X/* updateslot - update a slot definition */
  1849. XLOCAL updateslot(args,slotname,defexpr)
  1850. X  LVAL args,slotname,defexpr;
  1851. X{
  1852. X    LVAL tmp;
  1853. X    for (; consp(args); args = cdr(args))
  1854. X    if (slotname == car(car(args))) {
  1855. X        if (defexpr != NIL) {
  1856. X        xlsave1(tmp);
  1857. X        tmp = newclosure(NIL,s_lambda,xlenv,xlfenv);
  1858. X        setbody(tmp,cons(defexpr,NIL));
  1859. X        tmp = cons(tmp,NIL);
  1860. X        defexpr = tmp;
  1861. X        xlpop();
  1862. X        }
  1863. X        rplaca(cdr(car(args)),defexpr);
  1864. X        break;
  1865. X    }
  1866. X    if (args == NIL)
  1867. X    xlerror("unknown slot name",slotname);
  1868. X}
  1869. X
  1870. SHAR_EOF
  1871. if test 10906 -ne "`wc -c 'xlstruct.c'`"
  1872. then
  1873.     echo shar: error transmitting "'xlstruct.c'" '(should have been 10906 characters)'
  1874. fi
  1875. echo shar: extracting "'xlsubr.c'" '(3858 characters)'
  1876. if test -f 'xlsubr.c'
  1877. then
  1878.     echo shar: over-writing existing file "'xlsubr.c'"
  1879. fi
  1880. sed 's/^X//' << \SHAR_EOF > 'xlsubr.c'
  1881. X/* xlsubr - xlisp builtin function support routines */
  1882. X/*    Copyright (c) 1985, by David Michael Betz
  1883. X    All Rights Reserved
  1884. X    Permission is granted for unrestricted non-commercial use    */
  1885. X
  1886. X#include "xlisp.h"
  1887. X
  1888. X/* external variables */
  1889. Xextern LVAL k_test,k_tnot,s_eql;
  1890. X
  1891. X/* xlsubr - define a builtin function */
  1892. XLVAL xlsubr(sname,type,fcn,offset)
  1893. X  char *sname; int type; LVAL (*fcn)(); int offset;
  1894. X{
  1895. X    LVAL sym;
  1896. X    sym = xlenter(sname);
  1897. X    setfunction(sym,cvsubr(fcn,type,offset));
  1898. X    return (sym);
  1899. X}
  1900. X
  1901. X/* xlgetkeyarg - get a keyword argument */
  1902. Xint xlgetkeyarg(key,pval)
  1903. X  LVAL key,*pval;
  1904. X{
  1905. X    LVAL *argv=xlargv;
  1906. X    int argc=xlargc;
  1907. X    for (argv = xlargv, argc = xlargc; (argc -= 2) >= 0; argv += 2) {
  1908. X    if (*argv == key) {
  1909. X        *pval = *++argv;
  1910. X        return (TRUE);
  1911. X    }
  1912. X    }
  1913. X    return (FALSE);
  1914. X}
  1915. X
  1916. X/* xlgkfixnum - get a fixnum keyword argument */
  1917. Xint xlgkfixnum(key,pval)
  1918. X  LVAL key,*pval;
  1919. X{
  1920. X    if (xlgetkeyarg(key,pval)) {
  1921. X    if (!fixp(*pval))
  1922. X        xlbadtype(*pval);
  1923. X    return (TRUE);
  1924. X    }
  1925. X    return (FALSE);
  1926. X}
  1927. X
  1928. X/* xltest - get the :test or :test-not keyword argument */
  1929. Xxltest(pfcn,ptresult)
  1930. X  LVAL *pfcn; int *ptresult;
  1931. X{
  1932. X    if (xlgetkeyarg(k_test,pfcn))    /* :test */
  1933. X    *ptresult = TRUE;
  1934. X    else if (xlgetkeyarg(k_tnot,pfcn))    /* :test-not */
  1935. X    *ptresult = FALSE;
  1936. X    else {
  1937. X    *pfcn = getfunction(s_eql);
  1938. X    *ptresult = TRUE;
  1939. X    }
  1940. X}
  1941. X
  1942. X/* xlgetfile - get a file or stream */
  1943. XLVAL xlgetfile()
  1944. X{
  1945. X    LVAL arg;
  1946. X
  1947. X    /* get a file or stream (cons) or nil */
  1948. X    if (arg = xlgetarg()) {
  1949. X    if (streamp(arg)) {
  1950. X        if (getfile(arg) == NULL)
  1951. X        xlfail("file not open");
  1952. X    }
  1953. X    else if (!ustreamp(arg))
  1954. X        xlerror("bad argument type",arg);
  1955. X    }
  1956. X    return (arg);
  1957. X}
  1958. X
  1959. X/* xlgetfname - get a filename */
  1960. XLVAL xlgetfname()
  1961. X{
  1962. X    LVAL name;
  1963. X
  1964. X    /* get the next argument */
  1965. X    name = xlgetarg();
  1966. X
  1967. X    /* get the filename string */
  1968. X    if (symbolp(name))
  1969. X    name = getpname(name);
  1970. X    else if (!stringp(name))
  1971. X    xlerror("bad argument type",name);
  1972. X
  1973. X    /* return the name */
  1974. X    return (name);
  1975. X}
  1976. X
  1977. X/* needsextension - check if a filename needs an extension */
  1978. Xint needsextension(name)
  1979. X  char *name;
  1980. X{
  1981. X    char *p;
  1982. X
  1983. X    /* check for an extension */
  1984. X    for (p = &name[strlen(name)]; --p >= &name[0]; )
  1985. X    if (*p == '.')
  1986. X        return (FALSE);
  1987. X    else if (!islower(*p) && !isupper(*p) && !isdigit(*p))
  1988. X        return (TRUE);
  1989. X
  1990. X    /* no extension found */
  1991. X    return (TRUE);
  1992. X}
  1993. X
  1994. X/* xlbadtype - report a "bad argument type" error */
  1995. XLVAL xlbadtype(arg)
  1996. X  LVAL arg;
  1997. X{
  1998. X    xlerror("bad argument type",arg);
  1999. X}
  2000. X
  2001. X/* xltoofew - report a "too few arguments" error */
  2002. XLVAL xltoofew()
  2003. X{
  2004. X    xlfail("too few arguments");
  2005. X}
  2006. X
  2007. X/* xltoomany - report a "too many arguments" error */
  2008. Xxltoomany()
  2009. X{
  2010. X    xlfail("too many arguments");
  2011. X}
  2012. X
  2013. X/* eq - internal eq function */
  2014. Xint eq(arg1,arg2)
  2015. X  LVAL arg1,arg2;
  2016. X{
  2017. X    return (arg1 == arg2);
  2018. X}
  2019. X
  2020. X/* eql - internal eql function */
  2021. Xint eql(arg1,arg2)
  2022. X  LVAL arg1,arg2;
  2023. X{
  2024. X    /* compare the arguments */
  2025. X    if (arg1 == arg2)
  2026. X    return (TRUE);
  2027. X    else if (arg1) {
  2028. X    switch (ntype(arg1)) {
  2029. X    case FIXNUM:
  2030. X        return (fixp(arg2) ? getfixnum(arg1)==getfixnum(arg2) : FALSE);
  2031. X    case FLONUM:
  2032. X        return (floatp(arg2) ? getflonum(arg1)==getflonum(arg2) : FALSE);
  2033. X    default:
  2034. X        return (FALSE);
  2035. X    }
  2036. X    }
  2037. X    else
  2038. X    return (FALSE);
  2039. X}
  2040. X
  2041. X/* equal - internal equal function */
  2042. Xint equal(arg1,arg2)
  2043. X  LVAL arg1,arg2;
  2044. X{
  2045. X    /* compare the arguments */
  2046. X    if (arg1 == arg2)
  2047. X    return (TRUE);
  2048. X    else if (arg1) {
  2049. X    switch (ntype(arg1)) {
  2050. X    case FIXNUM:
  2051. X        return (fixp(arg2) ? getfixnum(arg1)==getfixnum(arg2) : FALSE);
  2052. X    case FLONUM:
  2053. X        return (floatp(arg2) ? getflonum(arg1)==getflonum(arg2) : FALSE);
  2054. X    case STRING:
  2055. X        return (stringp(arg2) ? strcmp(getstring(arg1),
  2056. X                       getstring(arg2)) == 0 : FALSE);
  2057. X    case CONS:
  2058. X        return (consp(arg2) ? equal(car(arg1),car(arg2))
  2059. X                   && equal(cdr(arg1),cdr(arg2)) : FALSE);
  2060. X    default:
  2061. X        return (FALSE);
  2062. X    }
  2063. X    }
  2064. X    else
  2065. X    return (FALSE);
  2066. X}
  2067. SHAR_EOF
  2068. if test 3858 -ne "`wc -c 'xlsubr.c'`"
  2069. then
  2070.     echo shar: error transmitting "'xlsubr.c'" '(should have been 3858 characters)'
  2071. fi
  2072. echo shar: extracting "'xlsym.c'" '(5057 characters)'
  2073. if test -f 'xlsym.c'
  2074. then
  2075.     echo shar: over-writing existing file "'xlsym.c'"
  2076. fi
  2077. sed 's/^X//' << \SHAR_EOF > 'xlsym.c'
  2078. X/* xlsym - symbol handling routines */
  2079. X/*    Copyright (c) 1985, by David Michael Betz
  2080. X    All Rights Reserved
  2081. X    Permission is granted for unrestricted non-commercial use    */
  2082. X
  2083. X#include "xlisp.h"
  2084. X
  2085. X/* external variables */
  2086. Xextern LVAL obarray,s_unbound;
  2087. Xextern LVAL xlenv,xlfenv,xldenv;
  2088. X
  2089. X/* forward declarations */
  2090. XFORWARD LVAL findprop();
  2091. X
  2092. X/* xlenter - enter a symbol into the obarray */
  2093. XLVAL xlenter(name)
  2094. X  char *name;
  2095. X{
  2096. X    LVAL sym,array;
  2097. X    int i;
  2098. X
  2099. X    /* check for nil */
  2100. X    if (strcmp(name,"NIL") == 0)
  2101. X    return (NIL);
  2102. X
  2103. X    /* check for symbol already in table */
  2104. X    array = getvalue(obarray);
  2105. X    i = hash(name,HSIZE);
  2106. X    for (sym = getelement(array,i); sym; sym = cdr(sym))
  2107. X    if (strcmp(name,getstring(getpname(car(sym)))) == 0)
  2108. X        return (car(sym));
  2109. X
  2110. X    /* make a new symbol node and link it into the list */
  2111. X    xlsave1(sym);
  2112. X    sym = consd(getelement(array,i));
  2113. X    rplaca(sym,xlmakesym(name));
  2114. X    setelement(array,i,sym);
  2115. X    xlpop();
  2116. X
  2117. X    /* return the new symbol */
  2118. X    return (car(sym));
  2119. X}
  2120. X
  2121. X/* xlmakesym - make a new symbol node */
  2122. XLVAL xlmakesym(name)
  2123. X  char *name;
  2124. X{
  2125. X    LVAL sym;
  2126. X    sym = cvsymbol(name);
  2127. X    if (*name == ':')
  2128. X    setvalue(sym,sym);
  2129. X    return (sym);
  2130. X}
  2131. X
  2132. X/* xlgetvalue - get the value of a symbol (with check) */
  2133. XLVAL xlgetvalue(sym)
  2134. X  LVAL sym;
  2135. X{
  2136. X    LVAL val;
  2137. X
  2138. X    /* look for the value of the symbol */
  2139. X    while ((val = xlxgetvalue(sym)) == s_unbound)
  2140. X    xlunbound(sym);
  2141. X
  2142. X    /* return the value */
  2143. X    return (val);
  2144. X}
  2145. X
  2146. X/* xlxgetvalue - get the value of a symbol */
  2147. XLVAL xlxgetvalue(sym)
  2148. X  LVAL sym;
  2149. X{
  2150. X    register LVAL fp,ep;
  2151. X    LVAL val;
  2152. X
  2153. X    /* check the environment list */
  2154. X    for (fp = xlenv; fp; fp = cdr(fp))
  2155. X
  2156. X    /* check for an instance variable */
  2157. X    if ((ep = car(fp)) && objectp(car(ep))) {
  2158. X        if (xlobgetvalue(ep,sym,&val))
  2159. X        return (val);
  2160. X    }
  2161. X
  2162. X    /* check an environment stack frame */
  2163. X    else {
  2164. X        for (; ep; ep = cdr(ep))
  2165. X        if (sym == car(car(ep)))
  2166. X            return (cdr(car(ep)));
  2167. X    }
  2168. X
  2169. X    /* return the global value */
  2170. X    return (getvalue(sym));
  2171. X}
  2172. X
  2173. X/* xlsetvalue - set the value of a symbol */
  2174. Xxlsetvalue(sym,val)
  2175. X  LVAL sym,val;
  2176. X{
  2177. X    register LVAL fp,ep;
  2178. X
  2179. X    /* look for the symbol in the environment list */
  2180. X    for (fp = xlenv; fp; fp = cdr(fp))
  2181. X
  2182. X    /* check for an instance variable */
  2183. X    if ((ep = car(fp)) && objectp(car(ep))) {
  2184. X        if (xlobsetvalue(ep,sym,val))
  2185. X        return;
  2186. X    }
  2187. X
  2188. X    /* check an environment stack frame */
  2189. X    else {
  2190. X        for (; ep; ep = cdr(ep))
  2191. X        if (sym == car(car(ep))) {
  2192. X            rplacd(car(ep),val);
  2193. X            return;
  2194. X        }
  2195. X    }
  2196. X
  2197. X    /* store the global value */
  2198. X    setvalue(sym,val);
  2199. X}
  2200. X
  2201. X/* xlgetfunction - get the functional value of a symbol (with check) */
  2202. XLVAL xlgetfunction(sym)
  2203. X  LVAL sym;
  2204. X{
  2205. X    LVAL val;
  2206. X
  2207. X    /* look for the functional value of the symbol */
  2208. X    while ((val = xlxgetfunction(sym)) == s_unbound)
  2209. X    xlfunbound(sym);
  2210. X
  2211. X    /* return the value */
  2212. X    return (val);
  2213. X}
  2214. X
  2215. X/* xlxgetfunction - get the functional value of a symbol */
  2216. XLVAL xlxgetfunction(sym)
  2217. X  LVAL sym;
  2218. X{
  2219. X    register LVAL fp,ep;
  2220. X
  2221. X    /* check the environment list */
  2222. X    for (fp = xlfenv; fp; fp = cdr(fp))
  2223. X    for (ep = car(fp); ep; ep = cdr(ep))
  2224. X        if (sym == car(car(ep)))
  2225. X        return (cdr(car(ep)));
  2226. X
  2227. X    /* return the global value */
  2228. X    return (getfunction(sym));
  2229. X}
  2230. X
  2231. X/* xlsetfunction - set the functional value of a symbol */
  2232. Xxlsetfunction(sym,val)
  2233. X  LVAL sym,val;
  2234. X{
  2235. X    register LVAL fp,ep;
  2236. X
  2237. X    /* look for the symbol in the environment list */
  2238. X    for (fp = xlfenv; fp; fp = cdr(fp))
  2239. X    for (ep = car(fp); ep; ep = cdr(ep))
  2240. X        if (sym == car(car(ep))) {
  2241. X        rplacd(car(ep),val);
  2242. X        return;
  2243. X        }
  2244. X
  2245. X    /* store the global value */
  2246. X    setfunction(sym,val);
  2247. X}
  2248. X
  2249. X/* xlgetprop - get the value of a property */
  2250. XLVAL xlgetprop(sym,prp)
  2251. X  LVAL sym,prp;
  2252. X{
  2253. X    LVAL p;
  2254. X    return ((p = findprop(sym,prp)) ? car(p) : NIL);
  2255. X}
  2256. X
  2257. X/* xlputprop - put a property value onto the property list */
  2258. Xxlputprop(sym,val,prp)
  2259. X  LVAL sym,val,prp;
  2260. X{
  2261. X    LVAL pair;
  2262. X    if (pair = findprop(sym,prp))
  2263. X    rplaca(pair,val);
  2264. X    else
  2265. X    setplist(sym,cons(prp,cons(val,getplist(sym))));
  2266. X}
  2267. X
  2268. X/* xlremprop - remove a property from a property list */
  2269. Xxlremprop(sym,prp)
  2270. X  LVAL sym,prp;
  2271. X{
  2272. X    LVAL last,p;
  2273. X    last = NIL;
  2274. X    for (p = getplist(sym); consp(p) && consp(cdr(p)); p = cdr(last)) {
  2275. X    if (car(p) == prp)
  2276. X        if (last)
  2277. X        rplacd(last,cdr(cdr(p)));
  2278. X        else
  2279. X        setplist(sym,cdr(cdr(p)));
  2280. X    last = cdr(p);
  2281. X    }
  2282. X}
  2283. X
  2284. X/* findprop - find a property pair */
  2285. XLOCAL LVAL findprop(sym,prp)
  2286. X  LVAL sym,prp;
  2287. X{
  2288. X    LVAL p;
  2289. X    for (p = getplist(sym); consp(p) && consp(cdr(p)); p = cdr(cdr(p)))
  2290. X    if (car(p) == prp)
  2291. X        return (cdr(p));
  2292. X    return (NIL);
  2293. X}
  2294. X
  2295. X/* hash - hash a symbol name string */
  2296. Xint hash(str,len)
  2297. X  char *str;
  2298. X{
  2299. X    int i;
  2300. X    for (i = 0; *str; )
  2301. X    i = (i << 2) ^ *str++;
  2302. X    i %= len;
  2303. X    return (i < 0 ? -i : i);
  2304. X}
  2305. X
  2306. X/* xlsinit - symbol initialization routine */
  2307. Xxlsinit()
  2308. X{
  2309. X    LVAL array,p;
  2310. X
  2311. X    /* initialize the obarray */
  2312. X    obarray = xlmakesym("*OBARRAY*");
  2313. X    array = newvector(HSIZE);
  2314. X    setvalue(obarray,array);
  2315. X
  2316. X    /* add the symbol *OBARRAY* to the obarray */
  2317. X    p = consa(obarray);
  2318. X    setelement(array,hash("*OBARRAY*",HSIZE),p);
  2319. X}
  2320. SHAR_EOF
  2321. if test 5057 -ne "`wc -c 'xlsym.c'`"
  2322. then
  2323.     echo shar: error transmitting "'xlsym.c'" '(should have been 5057 characters)'
  2324. fi
  2325. echo shar: extracting "'xlsys.c'" '(3335 characters)'
  2326. if test -f 'xlsys.c'
  2327. then
  2328.     echo shar: over-writing existing file "'xlsys.c'"
  2329. fi
  2330. sed 's/^X//' << \SHAR_EOF > 'xlsys.c'
  2331. X/* xlsys.c - xlisp builtin system functions */
  2332. X/*    Copyright (c) 1985, by David Michael Betz
  2333. X    All Rights Reserved
  2334. X    Permission is granted for unrestricted non-commercial use    */
  2335. X
  2336. X#include "xlisp.h"
  2337. X
  2338. X/* external variables */
  2339. Xextern jmp_buf top_level;
  2340. Xextern FILE *tfp;
  2341. X
  2342. X/* external symbols */
  2343. Xextern LVAL a_subr,a_fsubr,a_cons,a_symbol;
  2344. Xextern LVAL a_fixnum,a_flonum,a_string,a_object,a_stream;
  2345. Xextern LVAL a_vector,a_closure,a_char,a_ustream;
  2346. Xextern LVAL k_verbose,k_print;
  2347. Xextern LVAL true;
  2348. X
  2349. X/* external routines */
  2350. Xextern FILE *osaopen();
  2351. X
  2352. X/* xload - read and evaluate expressions from a file */
  2353. XLVAL xload()
  2354. X{
  2355. X    unsigned char *name;
  2356. X    int vflag,pflag;
  2357. X    LVAL arg;
  2358. X
  2359. X    /* get the file name */
  2360. X    name = getstring(xlgetfname());
  2361. X
  2362. X    /* get the :verbose flag */
  2363. X    if (xlgetkeyarg(k_verbose,&arg))
  2364. X    vflag = (arg != NIL);
  2365. X    else
  2366. X    vflag = TRUE;
  2367. X
  2368. X    /* get the :print flag */
  2369. X    if (xlgetkeyarg(k_print,&arg))
  2370. X    pflag = (arg != NIL);
  2371. X    else
  2372. X    pflag = FALSE;
  2373. X
  2374. X    /* load the file */
  2375. X    return (xlload(name,vflag,pflag) ? true : NIL);
  2376. X}
  2377. X
  2378. X/* xtranscript - open or close a transcript file */
  2379. XLVAL xtranscript()
  2380. X{
  2381. X    unsigned char *name;
  2382. X
  2383. X    /* get the transcript file name */
  2384. X    name = (moreargs() ? getstring(xlgetfname()) : NULL);
  2385. X    xllastarg();
  2386. X
  2387. X    /* close the current transcript */
  2388. X    if (tfp) osclose(tfp);
  2389. X
  2390. X    /* open the new transcript */
  2391. X    tfp = (name ? osaopen(name,"w") : NULL);
  2392. X
  2393. X    /* return T if a transcript is open, NIL otherwise */
  2394. X    return (tfp ? true : NIL);
  2395. X}
  2396. X
  2397. X/* xtype - return type of a thing */
  2398. XLVAL xtype()
  2399. X{
  2400. X    LVAL arg;
  2401. X
  2402. X    if (!(arg = xlgetarg()))
  2403. X    return (NIL);
  2404. X
  2405. X    switch (ntype(arg)) {
  2406. X    case SUBR:        return (a_subr);
  2407. X    case FSUBR:        return (a_fsubr);
  2408. X    case CONS:        return (a_cons);
  2409. X    case SYMBOL:    return (a_symbol);
  2410. X    case FIXNUM:    return (a_fixnum);
  2411. X    case FLONUM:    return (a_flonum);
  2412. X    case STRING:    return (a_string);
  2413. X    case OBJECT:    return (a_object);
  2414. X    case STREAM:    return (a_stream);
  2415. X    case VECTOR:    return (a_vector);
  2416. X    case CLOSURE:    return (a_closure);
  2417. X    case CHAR:        return (a_char);
  2418. X    case USTREAM:    return (a_ustream);
  2419. X    case STRUCT:    return (getelement(arg,0));
  2420. X    default:        xlfail("bad node type");
  2421. X    }
  2422. X}
  2423. X
  2424. X/* xbaktrace - print the trace back stack */
  2425. XLVAL xbaktrace()
  2426. X{
  2427. X    LVAL num;
  2428. X    int n;
  2429. X
  2430. X    if (moreargs()) {
  2431. X    num = xlgafixnum();
  2432. X    n = getfixnum(num);
  2433. X    }
  2434. X    else
  2435. X    n = -1;
  2436. X    xllastarg();
  2437. X    xlbaktrace(n);
  2438. X    return (NIL);
  2439. X}
  2440. X
  2441. X/* xexit - get out of xlisp */
  2442. XLVAL xexit()
  2443. X{
  2444. X    xllastarg();
  2445. X    wrapup();
  2446. X}
  2447. X
  2448. X/* xpeek - peek at a location in memory */
  2449. XLVAL xpeek()
  2450. X{
  2451. X    LVAL num;
  2452. X    int *adr;
  2453. X
  2454. X    /* get the address */
  2455. X    num = xlgafixnum(); adr = (int *)getfixnum(num);
  2456. X    xllastarg();
  2457. X
  2458. X    /* return the value at that address */
  2459. X    return (cvfixnum((FIXTYPE)*adr));
  2460. X}
  2461. X
  2462. X/* xpoke - poke a value into memory */
  2463. XLVAL xpoke()
  2464. X{
  2465. X    LVAL val;
  2466. X    int *adr;
  2467. X
  2468. X    /* get the address and the new value */
  2469. X    val = xlgafixnum(); adr = (int *)getfixnum(val);
  2470. X    val = xlgafixnum();
  2471. X    xllastarg();
  2472. X
  2473. X    /* store the new value */
  2474. X    *adr = (int)getfixnum(val);
  2475. X
  2476. X    /* return the new value */
  2477. X    return (val);
  2478. X}
  2479. X
  2480. X/* xaddrs - get the address of an XLISP node */
  2481. XLVAL xaddrs()
  2482. X{
  2483. X    LVAL val;
  2484. X
  2485. X    /* get the node */
  2486. X    val = xlgetarg();
  2487. X    xllastarg();
  2488. X
  2489. X    /* return the address of the node */
  2490. X    return (cvfixnum((FIXTYPE)val));
  2491. X}
  2492. X
  2493. SHAR_EOF
  2494. if test 3335 -ne "`wc -c 'xlsys.c'`"
  2495. then
  2496.     echo shar: error transmitting "'xlsys.c'" '(should have been 3335 characters)'
  2497. fi
  2498. #    End of shell archive
  2499. exit 0
  2500. -- 
  2501. Gary Murphy                   uunet!mitel!sce!cognos!garym
  2502.                               (garym%cognos.uucp@uunet.uu.net)
  2503. (613) 738-1338 x5537          Cognos Inc. P.O. Box 9707 Ottawa K1G 3N3
  2504. "There are many things which do not concern the process" - Joan of Arc
  2505.  
  2506.